#include <sys_config.h>
#include <retcode.h>
#include <types.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <bus/i2c/i2c.h>
#include <osal/osal.h>

#include "tun_sharp6401.h"

#if ((SYS_TUN_MODULE == SHARP6401) || (SYS_TUN_MODULE == ANY_TUNER))

#define NIM_PRINTF(...)
//#define NIM_PRINTF libc_printf

struct COFDM_TUNER_CONFIG_EXT stSHARP6401_Config[2];
static UINT8 sharp6401_tuner_cnt = 0;
/*****************************************************************************
* INT32 tun_sharp6401_init(struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config)
*
* Tuner sharp6401 Initialization
*
* Arguments:
*  Parameter1: struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config		: pointer for Tuner configuration structure 
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tun_sharp6401_init(UINT32 *tuner_id,struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config)
{
	/* check Tuner Configuration structure is available or not */
	if ((ptrTuner_Config == NULL))
		return ERR_FAILUE;
	
	MEMCPY(&stSHARP6401_Config[sharp6401_tuner_cnt], ptrTuner_Config, sizeof(struct COFDM_TUNER_CONFIG_EXT));
	sharp6401_tuner_cnt++;
	return SUCCESS;
}

/*****************************************************************************
* INT32 tun_sharp6401_status(UINT8 *lock)
*
* Tuner read operation
*
* Arguments:
*  Parameter1: UINT8 *lock		: Phase lock status
*
* Return Value: INT32			: Result
*****************************************************************************/

INT32 tun_sharp6401_status(UINT32 tuner_id,UINT8 *lock)
{
	INT32 result;
	UINT8 data;	
	
	result = stSHARP6401_Config[tuner_id].Tuner_Read(stSHARP6401_Config[tuner_id].i2c_type_id,stSHARP6401_Config[tuner_id].cTuner_Base_Addr, &data, 1);
	*lock = ((data & 0x40) >> 6);	

	if((*lock) == 1)
	{
		NIM_PRINTF("PLL lock\n");
	}
	else
	{
		NIM_PRINTF("PLL unlock!!!\n");
	}

	return result;
}

/*****************************************************************************
* INT32 nim_sharp6401_control(UINT32 freq, UINT8 bandwidth,UINT8 AGC_Time_Const,UINT8 *data,UINT8 _i2c_cmd)
*
* Tuner write operation
*
* Arguments:
*  Parameter1: UINT32 freq		: Synthesiser programmable divider
*  Parameter2: UINT8 bandwidth		: channel bandwidth
*  Parameter3: UINT8 AGC_Time_Const	: AGC time constant
*  Parameter4: UINT8 *data		: 
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tun_sharp6401_control(UINT32 tuner_id,UINT32 freq, UINT8 bandwidth,UINT8 AGC_Time_Const,UINT8 *data,UINT8 _i2c_cmd)	
{
	INT32 result = 0;
	UINT32 tmp; 
	UINT16 Npro;	
	UINT8 CP1_0, BS4, BS3_1, ATC, R2_0, P5,CP2, MODE;
	UINT8 ATP2_0;
	//change ref divider according to diff bandwidth.
	/*N value*/ 

	UINT16 tuner_crystal = stSHARP6401_Config[tuner_id].cTuner_Crystal;

	if (tuner_crystal >= 1000)
	{
		// tuner crystal kHz, trans to Mhz.
		tuner_crystal = tuner_crystal/1000;
	}

	tmp=((freq+stSHARP6401_Config[tuner_id].wTuner_IF_Freq+(stSHARP6401_Config[tuner_id].cTuner_Step_Freq/2))*(stSHARP6401_Config[tuner_id].cTuner_Ref_DivRatio))/tuner_crystal;	

	Npro=tmp/1000;
	NIM_PRINTF("Tuner Set Freq Npro=%d\n",Npro);
	data[0] = (UINT8) ((Npro>>8)&0x7F);
	data[1] = (UINT8) ((Npro)&0xFF); 

	if (FAST_TIMECST_AGC == AGC_Time_Const)
		ATC = 0x01;
	else
		ATC = 0x00;

	ATP2_0 = stSHARP6401_Config[tuner_id].cTuner_AGC_TOP; // 3'b000	use recommendation

	if (28 == stSHARP6401_Config[tuner_id].cTuner_Ref_DivRatio)
	{
		R2_0 = 0x01;
	}
	else
	{
		NIM_PRINTF("tuner Unknow RefDevider!!!\n");
		return ERR_FAILURE;
	}
	
	// control byte 1.
	data[2] = (UINT8)(0x80 | R2_0 | ((ATP2_0<<3)&0x38));
	
	/*CP */
	CP1_0 = 2;	// 2'b10
	CP2 = 0;
	MODE = 0;
		
	if (freq < 161000)		// low band
	{
		BS3_1 = 0x01;
		
	}
	else if (freq<426000)	// mid band VHF
	{
		BS3_1 = 0x02;
		
	}
	else				// high band UHF
	{
		BS3_1 = 0x04;
	}

	BS4=0x00;
	P5 =0x01;
	
	// control byte 2.
	data[3] = (UINT8)(((CP1_0<<6)&0xc0)  | ((P5<<4)&0x10) |((BS4<<3)&0x08) | (BS3_1&0x07));

	data[4] = (UINT8)(0xC0 |  ((ATC<<5)&0x20) | ((MODE<<4)&0x10) | ((CP2<<1)&0x20) |0x01);	


	if(stSHARP6401_Config[tuner_id].Tuner_Write!=NULL)
	{
		if(_i2c_cmd==_1st_i2c_cmd)
		{
			libc_printf("DB1=%x \n",data[0]);
			libc_printf("DB2=%x \n",data[1]);
			libc_printf("CB1=%x \n",data[2]);
			libc_printf("CB2=%x \n", data[3]);
			libc_printf("CB3=%x \n",data[4]);
			
			result = stSHARP6401_Config[tuner_id].Tuner_Write(stSHARP6401_Config[tuner_id].i2c_type_id,stSHARP6401_Config[tuner_id].cTuner_Base_Addr, data, 5);
		}
	}

	if ((AGC_Time_Const == FAST_TIMECST_AGC) && (_i2c_cmd==_1st_i2c_cmd))
	{
		//just wait once 100ms in ATC = 1 state.
		osal_task_sleep(100);	
	}
	if(result==0)
	{
		NIM_PRINTF("tuner i2c write success!!!\n");
		return SUCCESS;
	}
	else
	{
		NIM_PRINTF("tuner i2c write fail!!!\n");
		return result;
	}

}

#endif

